package com.ray.validate.support.utils;

import com.ray.validate.*;
import com.ray.validate.support.exception.ParamsException;
import com.ray.validate.support.rule.*;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.constraints.Range;
import org.springframework.util.StringUtils;

import javax.validation.constraints.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;

/**
 * @author bo shen
 * @Description: 校验工具
 * @Class: ValidateUtil
 * @Package tf56.antcolonyums.validate.support.utils
 * @date 2019/11/19 14:32
 * @company <p>杭州传化陆鲸科技有限公司</p>
 * @updateRecord time(修改时间)  author(修改人)   desc(修改内容)
 */
@Slf4j
public class ValidateUtil {

    private static Map<Class<?>, Rule> ruleMap = new HashMap<>();

    static {
        log.info("初始化规则");
       // ruleMap.put(NotBlank.class, new NotBlankRule());
        ruleMap.put(org.hibernate.validator.constraints.NotBlank.class, new HiNotBlankRule());
        ruleMap.put(NotNull.class, new NotNullRule());
        ruleMap.put(ConditionBlank.class, new ConditionBlankRule());
        ruleMap.put(ConditionNotBlank.class, new ConditionNotBlankRule());
        ruleMap.put(ConditionNull.class, new ConditionNullRule());
        ruleMap.put(ConditionNotNull.class, new ConditionNotNullRule());
        ruleMap.put(ConditionIn.class, new ConditionInRule());
        ruleMap.put(Pattern.class, new PatternRule());
        ruleMap.put(Max.class, new MaxRule());
        ruleMap.put(Min.class, new MinRule());
        ruleMap.put(Size.class, new SizeRule());
        ruleMap.put(DecimalMin.class, new DecimalMinRule());
        ruleMap.put(DecimalMax.class, new DecimalMaxRule());
        ruleMap.put(Digits.class, new DigitsRule());
        ruleMap.put(Past.class, new PastRule());
       // ruleMap.put(Email.class, new EmailRule());
        ruleMap.put(org.hibernate.validator.constraints.Email.class, new EmailRule());
        ruleMap.put(Range.class, new RangeRule());

    }

    /**
     * 添加规则
     *
     * @param clazz
     * @param rule
     */
    public static void addRule(Class<?> clazz, Rule rule) {
        ruleMap.put(clazz, rule);
    }

    /**
     * 条件成立
     *
     * @param expression
     * @param message
     */
    public static void isTrue(boolean expression, String message) {
        isTrue(expression, new ParamsException(message));
    }

    /**
     * 条件成立
     *
     * @param expression
     */
    public static void isTrue(boolean expression, RuntimeException exception) {
        if (!expression) {
            throw exception;
        }
    }

    /**
     * 对象是空
     *
     * @param object
     * @param message
     */
    public static void isNull(Object object, String message) {
        isNull(object, new ParamsException(message));
    }

    /**
     * 对象是空
     *
     * @param object
     * @param exception
     */
    public static void isNull(Object object, RuntimeException exception) {
        if (object != null) {
            throw exception;
        }
    }

    /**
     * 对象不能为空
     *
     * @param object
     * @param message
     */
    public static void notNull(Object object, String message) {
        notNull(object, new ParamsException(message));
    }

    /**
     * 对象不能为空
     *
     * @param object
     */
    public static void notNull(Object object, RuntimeException exception) {
        if (object == null) {
            throw exception;
        }
    }


    /**
     * 文本不能为空
     *
     * @param text
     * @param message
     */
    public static void hasLength(String text, String message) {
        hasLength(text, new ParamsException(message));

    }

    /**
     * 文本不能为空
     *
     * @param text
     * @param exception
     */
    public static void hasLength(String text, RuntimeException exception) {
        if (!StringUtils.hasLength(text)) {
            throw exception;
        }
    }


    public static void hasText(String text, String message) {
        hasText(text, new ParamsException(message));
    }


    public static void hasText(String text, RuntimeException exception) {
        if (!StringUtils.hasText(text)) {
            throw exception;
        }
    }


    public static void notEmpty(Object[] array, String message) {
        notEmpty(array, new ParamsException(message));
    }

    public static void notEmpty(Object[] array, RuntimeException exception) {
        if (array == null || array.length == 0) {
            throw exception;
        }
    }


    public static void notEmpty(Collection<?> collection, String message) {
        notEmpty(collection, new ParamsException(message));
    }

    public static void notEmpty(Collection<?> collection, RuntimeException exception) {
        if (collection == null || collection.isEmpty()) {
            throw exception;
        }
    }

    /**
     * 最大值
     *
     * @param value
     * @param max
     * @param message
     */
    public static void max(String value, Long max, String message) {
        max(value, max, new ParamsException(message));
    }

    /**
     * 最大值
     *
     * @param value
     * @param max
     */
    public static void max(String value, Long max, RuntimeException exception) {
        hasLength(value, exception);
        long v = Long.valueOf(value);
        isTrue(v <= max, exception);
    }

    /**
     * 最大值
     *
     * @param value
     * @param max
     * @param message
     */
    public static void max(String value, Integer max, String message) {
        max(value, max, new ParamsException(message));
    }

    /**
     * 最大值
     *
     * @param value
     * @param max
     */
    public static void max(String value, Integer max, RuntimeException exception) {
        hasLength(value, exception);
        int v = Integer.valueOf(value);
        isTrue(v <= max, exception);
    }

    /**
     * 最大值
     *
     * @param value
     * @param max
     * @param message
     */
    public static void max(String value, Double max, String message) {
        max(value, max, new ParamsException(message));
    }

    /**
     * 最大值
     *
     * @param value
     * @param max
     */
    public static void max(String value, Double max, RuntimeException exception) {
        hasLength(value, exception);
        double v = Double.valueOf(value);
        isTrue(v <= max, exception);
    }


    /**
     * 最小值
     *
     * @param value
     * @param min
     * @param message
     */
    public static void min(String value, Long min, String message) {
        min(value, min, new ParamsException(message));
    }

    /**
     * 最小值
     *
     * @param value
     * @param min
     */
    public static void min(String value, Long min, RuntimeException exception) {
        hasLength(value, exception);
        long v = Long.valueOf(value);
        isTrue(v >= min, exception);
    }

    /**
     * 最小值
     *
     * @param value
     * @param min
     * @param message
     */
    public static void min(String value, Integer min, String message) {
        min(value, min, new ParamsException(message));
    }

    /**
     * 最大值
     *
     * @param value
     * @param min
     */
    public static void min(String value, Integer min, RuntimeException exception) {
        hasLength(value, exception);
        int v = Integer.valueOf(value);
        isTrue(v >= min, exception);
    }

    /**
     * 最小值
     *
     * @param value
     * @param min
     * @param message
     */
    public static void min(String value, Double min, String message) {
        min(value, min, new ParamsException(message));
    }

    /**
     * 最小值
     *
     * @param value
     * @param min
     */
    public static void min(String value, Double min, RuntimeException exception) {
        hasLength(value, exception);
        double v = Double.valueOf(value);
        isTrue(v >= min, exception);
    }

    public static void size(String value, int min, int max, String message) {
        size(value, min, max, new ParamsException(message));
    }

    public static void size(String value, int min, int max, RuntimeException exception) {
        hasLength(value, exception);
        int v = Integer.valueOf(value);
        isTrue(v >= min && v <= max, exception);
    }


    public static void notEmpty(Map<?, ?> map, String message) {
        notEmpty(map, new ParamsException(message));
    }

    public static void notEmpty(Map<?, ?> map, RuntimeException exception) {
        if (map == null || map.isEmpty()) {
            throw exception;
        }
    }

    public static void numberInList(Number status, List<Number> list, String message) {
        numberInList(status, list, new ParamsException(message));
    }

    public static void numberInList(Number status, List<Number> list, RuntimeException exception) {
        notNull(status, exception);
        notNull(list, exception);
        if (list.indexOf(status) < 0) {
            throw exception;
        }
    }

    /**
     * 基于校验框架的MT层数据校验
     *
     * @param params
     */
    public static void validate(Object params) {
        ValidateUtil.notNull(params, "校验对象不能为空");
        //获取每个属性
        Field[] fields = params.getClass().getDeclaredFields();
        for (Field field : fields) {
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {
                Rule rule = ruleMap.get(annotation.annotationType());
                if (rule != null) {
                    rule.rule(params, field.getName(), annotation);
                }
            }
        }
    }


    /**
     * 基于校验框架的MT层数据校验
     *
     * @param params
     */
    public static List<String> getValidateMsg(Object params) {
        ValidateUtil.notNull(params, "校验对象不能为空");
        List<String> msgs = new ArrayList<>();
        //获取每个属性
        Field[] fields = params.getClass().getDeclaredFields();
        for (Field field : fields) {
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {
                Rule rule = ruleMap.get(annotation.annotationType());
                if (rule != null) {
                    try {
                        rule.rule(params, field.getName(), annotation);
                    } catch (Exception e) {
                        msgs.add(e.getMessage());
                    }
                }
            }
        }
        return msgs;
    }

    /**
     * 基于校验框架的MT层数据校验
     *
     * @param paramss
     */
    public static void validate(Object... paramss) {
        for (Object params : paramss) {
            validate(params);
        }
    }

    /**
     * 基于校验框架的MT层数据校验
     *
     * @param params
     */
    public static <T> void validates(List<T> params) {
        ValidateUtil.notNull(params, "校验对象不能为空");
        params.forEach(p -> {
            validate(p);
        });
    }

    /**
     * 参数校验
     * @param value
     * @param annotation
     */
    public static void validateParams(Object value, Annotation annotation) {
        Rule rule = ruleMap.get(annotation.annotationType());
        if(rule != null){
            rule.rule(value,annotation);
        }
    }
}
